package org.pizza.nacos.loadBalancer;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;



/**
 * @author 高巍
 * @since 2020/11/28 3:31 下午
 */
@Slf4j
public class ServiceInstancesWatch implements ApplicationEventPublisherAware, CommandLineRunner {

    private final NacosDiscoveryProperties properties;
    private final NacosServiceManager nacosServiceManager;
    private final DiscoveryClient discoveryClient;
    private Set<String> watchServiceList = new LinkedHashSet<>();

    public ServiceInstancesWatch(NacosDiscoveryProperties nacosDiscoveryProperties, NacosServiceManager nacosServiceManager, DiscoveryClient discoveryClient) {
        this.properties = nacosDiscoveryProperties;
        this.nacosServiceManager = nacosServiceManager;
        this.discoveryClient = discoveryClient;
    }

    private ApplicationEventPublisher applicationEventPublisher;

    private void init() {
        NamingService namingService = nacosServiceManager.getNamingService(properties.getNacosProperties());
        List<String> serviceList = discoveryClient.getServices();
        log.info("watch ribbon.eager-load.clients:{}", serviceList);
        if (serviceList != null) {
            serviceList.forEach(s -> {
                try {
                    namingService.subscribe(s,properties.getGroup(), event -> {
                        if (event instanceof NamingEvent) {
                            if (log.isDebugEnabled()) {
                                log.debug("Nacos注册中心服务：{}，实例列表：{}", ((NamingEvent) event).getServiceName(), JSON.toJSONString(((NamingEvent) event).getInstances()));
                            }
                            applicationEventPublisher.publishEvent(new ServiceInstancesChangedEvent(this, (NamingEvent) event));
                        }
                    });
                    watchServiceList.add(s);
                } catch (NacosException e) {
                    log.error("订阅[{}]服务事件出现异常", s, e);
                }
            });
            log.info("watch success,service list:{}", watchServiceList);
        }
    }


    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }


    public Set<String> getWatchServiceList() {
        return watchServiceList;
    }

    public void setWatchServiceList(Set<String> watchServiceList) {
        this.watchServiceList = watchServiceList;
    }

    @Override
    public void run(String... args) throws Exception {
        this.init();
    }
}
